@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp empPara){
Emp emp = empService.login(empPara);
}
return emp!=null ?Result.success(emp):Result.error("账号或密码错误!");
}
}
Emp login(Emp empPara);
@Override
public Emp login(Emp empPara) {
return empMapper.login(empPara);
}
@Select("select * from emp where username=#{username} and password = #{password}")
Emp login(Emp empPara);
会话
会话跟踪
会话跟踪方法
【会话跟踪方案对比】
优点
缺点
@RestController
public class SessionController {
//设置Cookie
@GetMapping("/c1")
public Result cookie1(HttpServletResponse response){
response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie
return Result.success();
}
//获取Cookie
@GetMapping("/c2")
public Result cookie2(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if(cookie.getName().equals("login_username")){
System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie
}
}
return Result.success();
}
@GetMapping("/s1")
public Result session1(HttpSession session){
log.info("HttpSession-s1: {}", session.hashCode());
session.setAttribute("loginUser", "tom"); //往session中存储数据
return Result.success();
}
@GetMapping("/s2")
public Result session2(HttpServletRequest request){
HttpSession session = request.getSession();
log.info("HttpSession-s2: {}", session.hashCode());
Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
log.info("loginUser: {}", loginUser);
return Result.success(loginUser);
}
}
Base64
场景:登录验证
JWT生成
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
@Test
public void setJwt(){
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("name","haonan");
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, "mahaonan") //设置签名算法 参数:算法方式,密钥
.setClaims(claims) //自定义内容(载荷)
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //设置有效期为一个小时
.compact();
System.out.println(jwt);
}
//解析令牌
@Test
public void parseJwt(){
Claims claims = Jwts.parser()
.setSigningKey("mahaonan") //解析令牌需要的密钥(前面自己设置的)
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiaGFvbmFuIiwiaWQiOjEsImV4cCI6MTY4MDUyOTU0NH0.AFlglHswEkPupqSkTYyH0RQPWoH24rxzoY1JMeuNbno")
.getBody();
System.out.println(claims);
System.out.println(claims.get("name"));
}
【注意事项】
登录-生成令牌
public class JwtUtils {
private static String signKey = "mahaonan";
private static Long expire = 43200000L;
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
LoginController
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp empPara){
Emp emp = empService.login(empPara);
if(emp!=null){
Map<String,Object> claims = new HashMap<>();
claims.put("id",emp.getId());
claims.put("name",emp.getName());
claims.put("username",emp.getUsername());
String jwt = JwtUtils.generateJwt(claims);
return Result.success(jwt);
}
return Result.error("账号或密码错误!");
}
}
配置Filter:Filter类上加@WebFilter注解,配置拦截资源的路径,引导类(启动类)加上@ServletComponentScan开启Servlet组件支持
Application.java(启动类)
@ServletComponentScan //开启了对Servlet组件的支持
@SpringBootApplication
public class WebDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebDemoApplication.class, args);
}
}
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override //初始化方法,只执行一次
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init 初始化方法执行");
}
@Override //拦截请求后调用,调用多次
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter拦截了请求");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override //销毁方法,只执行一次
public void destroy() {
System.out.println("destroy 销毁方法执行");
}
}
顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序
步骤
LoginFilter
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse res = (HttpServletResponse) servletResponse;
//1.获取请求URL
String url = req.getRequestURL().toString();
//2.判断URL中是否包含login。是的话,放行
if(url.contains("login")){
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//3.获取请求头令牌token
String token = req.getHeader("token");
//4.判断令牌是否存在,不存在返回错误结果
if(!StringUtils.hasLength(token)){
Result error = Result.error("NOT_LOGIN");
//手动转换 对象---json
String errorJson = JSONObject.toJSONString(error);
res.getWriter().write(errorJson);
return;
}
//5.解析token,如果解析失败则返回错误结果
try{
JwtUtils.parseJWT(token);
}catch (Exception e){//解析失败
e.printStackTrace();
Result error = Result.error("Not_LOGIN");
//手动转换 对象---json
String errorJson = JSONObject.toJSONString(error);
res.getWriter().write(errorJson);
return;
}
//6.放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
快速入门
LoginCheckInterceptor
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override//目标资源方法运行前运行,返回true:放行 false:不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle ....");
return true;
}
@Override //目标资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle ....");
}
@Override //渲染视图完成后执行,最后执行的方法
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion ....");
}
}
@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
}
拦截路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
步骤
与Filter同理
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override//目标资源方法运行前运行,返回true:放行 false:不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle ....");
//1.获取请求URL
String url = request.getRequestURL().toString();
//2.判断URL中是否包含login。是的话,放行
if(url.contains("login")){
return true;
}
//3.获取请求头令牌token
String token = request.getHeader("token");
//4.判断令牌是否存在,不存在返回错误结果
if(!StringUtils.hasLength(token)){
Result error = Result.error("NOT_LOGIN");
//手动转换 对象---json
String errorJson = JSONObject.toJSONString(error);
response.getWriter().write(errorJson);
return false;
}
//5.解析token,如果解析失败则返回错误结果
try{
JwtUtils.parseJWT(token);
}catch (Exception e){//解析失败
e.printStackTrace();
Result error = Result.error("Not_LOGIN");
//手动转换 对象---json
String errorJson = JSONObject.toJSONString(error);
response.getWriter().write(errorJson);
return false;
}
return true;
}
}
开发过程中不可避免会遇到异常现象
出现异常,如何处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)//捕获所有异常
public Result ex(Exception e){
e.printStackTrace();
return Result.error("搞错了,你在哪儿瞎玩,联系管理员!");
}
}
@RestControllerAdvice = @ControllerAdvice + @ResponseBody